//------------------------------------------------------------------------------
// Fichiers d'ent�te utilis�s
//------------------------------------------------------------------------------
#include "Layer.hpp"
#include "Orientation.hpp"

//------------------------------------------------------------------------------
// Définition de constantes
//------------------------------------------------------------------------------

namespace ImageAnalysis
{

	//----------------------------------------------------------------------
	// Constructeur
	//----------------------------------------------------------------------
	Layer::Layer( int width, int height ):
	layerWidth(width),
	layerHeight(height),
	layerPixelNeighborHood(0)
	{
		// Création du tableau de voisinage
		layerPixelNeighborHood = new  PixelNeighborHood[ layerWidth * layerHeight ];

		// Initialisation du tableau de voisinage
		initializeNeighborHood();
	}

	//----------------------------------------------------------------------
	// Destructeur
	//----------------------------------------------------------------------
	Layer::~Layer( )
	{
		// Destruction du tableau de voisinage
		if( layerPixelNeighborHood != 0 )
		{	delete[] layerPixelNeighborHood; }
	}


    	//----------------------------------------------------------------------
	//
	//----------------------------------------------------------------------
	int Layer::GetWidth( )
	{
		return layerWidth;
	}
	
	
	//----------------------------------------------------------------------
	//
	//----------------------------------------------------------------------
	int Layer::GetHeight( )
	{
		return layerHeight;
	}
	
		//----------------------------------------------------------------------
	// Permet de récupérer l'index d'un pixel donnée
	//----------------------------------------------------------------------
	int Layer::GetPixelIndex( int x, int y )
	{
		return x + y*layerWidth;
	}
	
	//----------------------------------------------------------------------
	// Permet de récupérer l'index d'un pixel donnée
	//----------------------------------------------------------------------
	Layer::PixelNeighborHood& Layer::GetDirectPixelNeighborHood( int index )
	{
		return layerPixelNeighborHood[index];
	}
	
	//----------------------------------------------------------------------
	// Permet de récupérer le voisinage d'un pixel pour un index de pixel
	// donnée
	//----------------------------------------------------------------------
	int*  Layer::GetPixelNeighborHood( int index, int depth )
	{
		int squareSize = depth*2+1;
		int* neighbourHoodTable = new int [squareSize*squareSize];		


		// On commence par se positionner en haut à gauche
		// x . . . .
		// . x . . .
		// . . x . .
		// . . . . .
		// . . . . .
		for (int i=0; i<depth;++i)
		{
			index = layerPixelNeighborHood[index].index[Orientation::NORTH_WEST];
		}

		// On parcourt notre tableau ligne par ligne de haut en bas
		int indexNextLine = layerPixelNeighborHood[index].index[Orientation::SOUTH];
		for (int j=0; j<squareSize; ++j)
		{
			// On remplit notre tableau colonne par colonne de gauche à droite
			for (int k=0; k<squareSize; ++k)
			{
				neighbourHoodTable[k + j*squareSize] = layerPixelNeighborHood[index].index[Orientation::CENTER];
				index = layerPixelNeighborHood[index].index[Orientation::EAST];
			}
			index = indexNextLine;
			indexNextLine = layerPixelNeighborHood[index].index[Orientation::SOUTH];
		}

		// Construction de la région
		//int* region  = new Region(index%(layerWidth-1),index/(layerWidth-1),layerWidth,layerHeight);
		//region->Indexes = neighbourHoodTable;
		return neighbourHoodTable;
	}
	
	//----------------------------------------------------------------------
	//
	//----------------------------------------------------------------------
	int* Layer::GetPixelNeighborHood( int index, int width, int height )
	{
		int* neighbourHoodTable = new int [width*height];

		int indexNextLine = layerPixelNeighborHood[index].index[Orientation::SOUTH];
		for (int j=0; j<height; ++j)
		{
			// On remplit notre tableau colonne par colonne de gauche à droite
			for (int k=0; k<width; ++k)
			{
				neighbourHoodTable[k + j*width] = layerPixelNeighborHood[index].index[Orientation::CENTER];
				index = layerPixelNeighborHood[index].index[Orientation::EAST];
			}
			index = indexNextLine;
			indexNextLine = layerPixelNeighborHood[index].index[Orientation::SOUTH];
		}
		
		// Construction de la région
		//Region* region  = new Region(index%(layerWidth-1),index/(layerWidth-1),width,height);		
		//region->Indexes = neighbourHoodTable;		
		return neighbourHoodTable;
	}
	
	//----------------------------------------------------------------------
	//
	// pixelLocalIndex : indice du pixel dans le rep�e r�ion
	//----------------------------------------------------------------------
/*
	bool Layer::ContainInLocalRegion(Orientation::TOrientation orientation, int pixelLocalIndex, Region* region, int* nextPixelLocalIndex )
		{
		// Récupération du voisinage du pixel courant
		PixelNeighborHood& neighborHood = GetDirectPixelNeighborHood(region->Indexes[pixelLocalIndex]);
	
			// Calcul de l'index du voisin selon la direction souhaité dans la sous région
			switch( orientation )
			{
				case Orientation::NORTH_WEST:
					*nextPixelLocalIndex = pixelLocalIndex-1-region->Width;
					break;
				case Orientation::NORTH:
					*nextPixelLocalIndex = pixelLocalIndex-region->Width;
					break;
				case Orientation::NORTH_EAST:
					*nextPixelLocalIndex = pixelLocalIndex+1-region->Width;
					break;
				case Orientation::WEST:
					*nextPixelLocalIndex = pixelLocalIndex-1;
					break;
				case Orientation::CENTER:
					*nextPixelLocalIndex = pixelLocalIndex;
					break;
				case Orientation::EAST:
					*nextPixelLocalIndex = pixelLocalIndex+1;
					break;
				case Orientation::SOUTH_WEST:
					*nextPixelLocalIndex = pixelLocalIndex-1+region->Width;
					break;
				case Orientation::SOUTH:
					*nextPixelLocalIndex = pixelLocalIndex+region->Width;
					break;
				case Orientation::SOUTH_EAST:
					*nextPixelLocalIndex = pixelLocalIndex+1+region->Width;
					break;
				default: *nextPixelLocalIndex = -1;
			}
	
			// Comparaison entre la valeur du voisin dans la sous région et la valeur de voisin dans l'image global.
			// Si les indices correspondent alors il s'agit du même pixel et donc le voisin est contenu dans la zone.
			if( (*nextPixelLocalIndex > 0) && (*nextPixelLocalIndex < region->Width*region->Height) )
			{	return region->Indexes[*nextPixelLocalIndex] == neighborHood.index[orientation]; }
			else
			{ 	return false; }
		}*/
	
		//----------------------------------------------------------------------
		// Initilisation du tableau de voisinage
		//----------------------------------------------------------------------
		void Layer::initializeNeighborHood()
		{
			// Remarque :
			// Le schéma avant chaque partie du code suivant indique la
			// partie du voisinage initialisée par le code qui suit
	
			//  x . . x
			//  . . . .
			//  . . . .
			//  x . . x
			int indexBottomRight = layerHeight*layerWidth-1;
			int indexBottomLeft  = (layerHeight-1)*layerWidth;
			int indexTopRight    = layerWidth-1;
			int indexTopLeft     = 0;
			layerPixelNeighborHood[indexBottomRight].index[Orientation::NORTH_WEST] = (indexBottomRight-1) - layerWidth;
			layerPixelNeighborHood[indexBottomRight].index[Orientation::NORTH]      = indexBottomRight-layerWidth;
			layerPixelNeighborHood[indexBottomRight].index[Orientation::NORTH_EAST] = InvalidIndex;
			layerPixelNeighborHood[indexBottomRight].index[Orientation::WEST]       = indexBottomRight-1;
			layerPixelNeighborHood[indexBottomRight].index[Orientation::CENTER]     = indexBottomRight;
			layerPixelNeighborHood[indexBottomRight].index[Orientation::EAST]       = InvalidIndex;
			layerPixelNeighborHood[indexBottomRight].index[Orientation::SOUTH_WEST] = InvalidIndex;
			layerPixelNeighborHood[indexBottomRight].index[Orientation::SOUTH]      = InvalidIndex;
			layerPixelNeighborHood[indexBottomRight].index[Orientation::SOUTH_EAST] = InvalidIndex;
	
			layerPixelNeighborHood[indexBottomLeft].index[Orientation::NORTH_WEST] = InvalidIndex;
			layerPixelNeighborHood[indexBottomLeft].index[Orientation::NORTH]      = indexBottomLeft-layerWidth;
			layerPixelNeighborHood[indexBottomLeft].index[Orientation::NORTH_EAST] = (indexBottomLeft+1)-layerWidth;
			layerPixelNeighborHood[indexBottomLeft].index[Orientation::WEST]       = InvalidIndex;
			layerPixelNeighborHood[indexBottomLeft].index[Orientation::CENTER]     = indexBottomLeft;
			layerPixelNeighborHood[indexBottomLeft].index[Orientation::EAST]       = indexBottomLeft+1;
			layerPixelNeighborHood[indexBottomLeft].index[Orientation::SOUTH_WEST] = InvalidIndex;
			layerPixelNeighborHood[indexBottomLeft].index[Orientation::SOUTH]      = InvalidIndex;
			layerPixelNeighborHood[indexBottomLeft].index[Orientation::SOUTH_EAST] = InvalidIndex;
	
			layerPixelNeighborHood[indexTopRight].index[Orientation::NORTH_WEST] = InvalidIndex;
			layerPixelNeighborHood[indexTopRight].index[Orientation::NORTH]      = InvalidIndex;
			layerPixelNeighborHood[indexTopRight].index[Orientation::NORTH_EAST] = InvalidIndex;
			layerPixelNeighborHood[indexTopRight].index[Orientation::WEST]       = indexTopRight-1;
			layerPixelNeighborHood[indexTopRight].index[Orientation::CENTER]     = indexTopRight;
			layerPixelNeighborHood[indexTopRight].index[Orientation::EAST]       = InvalidIndex;
			layerPixelNeighborHood[indexTopRight].index[Orientation::SOUTH_WEST] = (indexTopRight-1)+layerWidth;
			layerPixelNeighborHood[indexTopRight].index[Orientation::SOUTH]      = indexTopRight+layerWidth;
			layerPixelNeighborHood[indexTopRight].index[Orientation::SOUTH_EAST] = InvalidIndex;
	
			layerPixelNeighborHood[indexTopLeft].index[Orientation::NORTH_WEST] = InvalidIndex;
			layerPixelNeighborHood[indexTopLeft].index[Orientation::NORTH]      = InvalidIndex;
			layerPixelNeighborHood[indexTopLeft].index[Orientation::NORTH_EAST] = InvalidIndex;
			layerPixelNeighborHood[indexTopLeft].index[Orientation::WEST]       = InvalidIndex;
			layerPixelNeighborHood[indexTopLeft].index[Orientation::CENTER]     = indexTopLeft;
			layerPixelNeighborHood[indexTopLeft].index[Orientation::EAST]       = indexTopLeft+1;
			layerPixelNeighborHood[indexTopLeft].index[Orientation::SOUTH_WEST] = InvalidIndex;
			layerPixelNeighborHood[indexTopLeft].index[Orientation::SOUTH]      = indexTopLeft+layerWidth;
			layerPixelNeighborHood[indexTopLeft].index[Orientation::SOUTH_EAST] = (indexTopLeft+1)+layerWidth;
	
			//  . x x .
			//  . . . .
			//  . . . .
			//  . . . .
			for( int index=1; index < layerWidth-1; ++index )
			{
				layerPixelNeighborHood[index].index[Orientation::NORTH_WEST] = InvalidIndex;
				layerPixelNeighborHood[index].index[Orientation::NORTH]      = InvalidIndex;
				layerPixelNeighborHood[index].index[Orientation::NORTH_EAST] = InvalidIndex;
				layerPixelNeighborHood[index].index[Orientation::WEST]       = index-1;
				layerPixelNeighborHood[index].index[Orientation::CENTER]     = index;
				layerPixelNeighborHood[index].index[Orientation::EAST]       = index+1;
				layerPixelNeighborHood[index].index[Orientation::SOUTH_WEST] = (index-1) + layerWidth;
				layerPixelNeighborHood[index].index[Orientation::SOUTH]      = index + layerWidth;
				layerPixelNeighborHood[index].index[Orientation::SOUTH_EAST] = (index+1) + layerWidth;
			}
	
			//  . . . .
			//  . . . x
			//  . . . x
			//  . . . .
			for( int index=layerWidth+(layerWidth-1); index < (layerHeight*layerWidth-1); index += layerWidth )
			{
				layerPixelNeighborHood[index].index[Orientation::NORTH_WEST] = (index-1)-layerWidth;
				layerPixelNeighborHood[index].index[Orientation::NORTH]      = index-layerWidth;
				layerPixelNeighborHood[index].index[Orientation::NORTH_EAST] = InvalidIndex;
				layerPixelNeighborHood[index].index[Orientation::WEST]       = index-1;
				layerPixelNeighborHood[index].index[Orientation::CENTER]     = index;
				layerPixelNeighborHood[index].index[Orientation::EAST]       = InvalidIndex;
				layerPixelNeighborHood[index].index[Orientation::SOUTH_WEST] = (index-1)+layerWidth;
				layerPixelNeighborHood[index].index[Orientation::SOUTH]      = index+layerWidth;
				layerPixelNeighborHood[index].index[Orientation::SOUTH_EAST] = InvalidIndex;
			}
	
			//  . . . .
			//  . . . .
			//  . . . .
			//  . x x .
			for( int index=layerWidth*(layerHeight-1)+1; index < (layerWidth*layerHeight)-1; ++index )
			{
				layerPixelNeighborHood[index].index[Orientation::NORTH_WEST] = (index-1)-layerWidth;
				layerPixelNeighborHood[index].index[Orientation::NORTH]      = index-layerWidth;
				layerPixelNeighborHood[index].index[Orientation::NORTH_EAST] = (index+1)-layerWidth;
				layerPixelNeighborHood[index].index[Orientation::WEST]       = index-1;
				layerPixelNeighborHood[index].index[Orientation::CENTER]     = index;
				layerPixelNeighborHood[index].index[Orientation::EAST]       = index+1;
				layerPixelNeighborHood[index].index[Orientation::SOUTH_WEST] = InvalidIndex;
				layerPixelNeighborHood[index].index[Orientation::SOUTH]      = InvalidIndex;
				layerPixelNeighborHood[index].index[Orientation::SOUTH_EAST] = InvalidIndex;
			}
	
			//  . . . .
			//  x . . .
			//  x . . .
			//  . . . .
			for( int index=layerWidth; index < layerWidth*(layerHeight-1); index += layerWidth )
			{
				layerPixelNeighborHood[index].index[Orientation::NORTH_WEST] = InvalidIndex;
				layerPixelNeighborHood[index].index[Orientation::NORTH]      = index-layerWidth;
				layerPixelNeighborHood[index].index[Orientation::NORTH_EAST] = (index+1)-layerWidth;
				layerPixelNeighborHood[index].index[Orientation::WEST]       = InvalidIndex;
				layerPixelNeighborHood[index].index[Orientation::CENTER]     = index;
				layerPixelNeighborHood[index].index[Orientation::EAST]       = index+1;
				layerPixelNeighborHood[index].index[Orientation::SOUTH_WEST] = InvalidIndex;
				layerPixelNeighborHood[index].index[Orientation::SOUTH]      = index+layerWidth;
				layerPixelNeighborHood[index].index[Orientation::SOUTH_EAST] = (index+1)+layerWidth;
			}
	
			//  . . . .
			//  . x x .
			//  . x x .
			//  . . . .
			for( int j=1; j < layerHeight-1; ++j )
			{
		for( int i=1; i < layerWidth-1; ++i )
			{
			int index = i + j*layerWidth;
			layerPixelNeighborHood[index].index[Orientation::NORTH_WEST] = (index-1)-layerWidth;
					layerPixelNeighborHood[index].index[Orientation::NORTH]      = index-layerWidth;
					layerPixelNeighborHood[index].index[Orientation::NORTH_EAST] = (index+1)-layerWidth;
					layerPixelNeighborHood[index].index[Orientation::WEST]       = index-1;
					layerPixelNeighborHood[index].index[Orientation::CENTER]     = index;
					layerPixelNeighborHood[index].index[Orientation::EAST]       = index+1;
					layerPixelNeighborHood[index].index[Orientation::SOUTH_WEST] = (index-1)+layerWidth;
					layerPixelNeighborHood[index].index[Orientation::SOUTH]      = index+layerWidth;
					layerPixelNeighborHood[index].index[Orientation::SOUTH_EAST] = (index+1)+layerWidth;
		}
			}
		}
}
